package com.tencent.wxcloudrun.manager;

import java.util.*;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import com.tencent.wxcloudrun.config.ApiResponse;
import com.tencent.wxcloudrun.domain.TActiUserImg;
import jakarta.validation.Valid;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson2.JSONObject;
import com.tencent.wxcloudrun.constant.RedisKeyConstant;
import com.tencent.wxcloudrun.domain.TActi;
import com.tencent.wxcloudrun.domain.TActiFill;
import com.tencent.wxcloudrun.domain.TActiReward;
import com.tencent.wxcloudrun.dto.ActiListResDTO;
import com.tencent.wxcloudrun.dto.QuartzJobDTO;
import com.tencent.wxcloudrun.dto.StoreProdAttrReqDTO;
import com.tencent.wxcloudrun.enums.ActiJoinKindEnum;
import com.tencent.wxcloudrun.enums.ActiJoinTypeEnum;
import com.tencent.wxcloudrun.enums.ActiStatEnum;
import com.tencent.wxcloudrun.enums.BusiTypeEnum;
import com.tencent.wxcloudrun.service.*;
import com.tencent.wxcloudrun.util.RedisUtil;
import com.tencent.wxcloudrun.vo.request.acti.*;
import com.tencent.wxcloudrun.vo.response.acti.*;
import com.tencent.wxcloudrun.vo.response.store.StoreProdQueryResVo;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestBody;

/**
 * @Author ZhaoZiYin
 * @Date 2025/4/22
 * @Description 活动管理端
 */
@Service
@Slf4j
public class ActiManager {

    @Resource
    private RedisUtil redisUtil;

    @Resource
    private TUserService userService;

    @Resource
    private TQuartzJobService quartzJobService;

    @Resource
    private TActiService actiService;

    @Resource
    private TActiRewardService actiRewardService;

    @Resource
    private TActiFillService actiFillService;

    @Resource
    private TActiJoinService actiJoinService;

    @Resource
    private TActiJoinFillService actiJoinFillService;

    @Resource
    private TActiJoinProdService actiJoinProdService;

    @Resource
    private TActiJoinProdAttrService actiJoinProdAttrService;

    @Resource
    private TActiUserImgService actiUserImgService;

    /**
     * @Author: ZhaoZiYin
     * @Date: 2025/4/22
     * @Params: [reqVo]
     * @Return: ActiAddResVo
     * @Description: 新增活动
     */
    @Transactional(rollbackFor = Exception.class)
    public ActiAddResVo add(ActiAddReqVo reqVo) {
        ActiAddResVo resVo = new ActiAddResVo();
        userService.checkAdmin(reqVo.getUserId());
        Long actiId = actiService.add(reqVo);
        actiRewardService.add(reqVo.getUserId(), actiId, reqVo.getRewardList());
        actiFillService.add(reqVo.getUserId(), actiId, reqVo.getFillList());
        this.saveRedis4Acti(actiId);
        resVo.setActiId(actiId);
        return resVo;
    }

    /**
     * @Author: ZhaoZiYin
     * @Date: 2025/4/22
     * @Params: [reqVo]
     * @Return: ActiUpdateResVo
     * @Description: 更新活动
     */
    @Transactional(rollbackFor = Exception.class)
    public ActiUpdateResVo update(ActiUpdateReqVo reqVo) {
        userService.checkAdmin(reqVo.getUserId());
        actiService.update(reqVo);
        actiRewardService.deleteByActiId(reqVo.getActiId());
        actiRewardService.add(reqVo.getUserId(), reqVo.getActiId(), reqVo.getRewardList());
        actiFillService.deleteByActiId(reqVo.getActiId());
        actiFillService.add(reqVo.getUserId(), reqVo.getActiId(), reqVo.getFillList());
        this.saveScheduleJob4Acti(reqVo.getActiId());
        this.saveRedis4Acti(reqVo.getActiId());
        return null;
    }

    /**
     * @Author: ZhaoZiYin
     * @Date: 2025/4/22
     * @Params: [reqVo]
     * @Return: ActiDeleteResVo
     * @Description: 删除活动
     */
    @Transactional(rollbackFor = Exception.class)
    public ActiDeleteResVo delete(ActiDeleteReqVo reqVo) {
        userService.checkAdmin(reqVo.getUserId());
        actiService.delete(reqVo.getUserId(), reqVo.getActiId());
        actiRewardService.delete(reqVo.getUserId(), reqVo.getActiId());
        actiFillService.delete(reqVo.getUserId(), reqVo.getActiId());
        quartzJobService.delScheduleJob4Acti(reqVo.getActiId());
        this.deleteRedis4Acti(reqVo.getActiId());
        return null;
    }

    /**
     * @Author: ZhaoZiYin
     * @Date: 2025/4/22
     * @Params: [reqVo]
     * @Return: ActiReleaseResVo
     * @Description: 发布活动
     */
    @Transactional(rollbackFor = Exception.class)
    public ActiReleaseResVo release(ActiReleaseReqVo reqVo) {
        userService.checkAdmin(reqVo.getUserId());
        actiService.release(reqVo.getUserId(), reqVo.getActiId());
        this.saveScheduleJob4Acti(reqVo.getActiId());
        this.saveRedis4Acti(reqVo.getActiId());
        return null;
    }

    /**
     * @Author: ZhaoZiYin
     * @Date: 2025/4/28
     * @Params: [actiId]
     * @Return: List<QuartzJobDTO>
     * @Description: 创建活动所有调度任务
     */
    public void saveScheduleJob4Acti(Long actiId) {
        TActi acti = actiService.getById(actiId);
        if (Objects.nonNull(acti) && acti.getActiStatus() != ActiStatEnum.DRAFT.getValue()) {
            List<QuartzJobDTO> quartzJobDTOList = new ArrayList<>(getJobListForActi(acti));
            if (acti.getSelectedFlag() == 1) {
                quartzJobDTOList.addAll(getJobList4ActiSelect(acti));
            }
            if (acti.getBlackFlag() == 1) {
                quartzJobDTOList.addAll(getJobList4ActiBlack(acti));
            }
            quartzJobService.delScheduleJob4Acti(actiId);
            quartzJobService.addScheduleJob(quartzJobDTOList);
        }
    }

    /**
     * @Author: ZhaoZiYin
     * @Date: 2025/4/28
     * @Params: [acti]
     * @Return: List<QuartzJobDTO>
     * @Description: 获取参与活动调度任务
     */
    public List<QuartzJobDTO> getJobListForActi(TActi acti) {
        List<QuartzJobDTO> quartzJobDTOList = new ArrayList<>(2);
        // 活动开始任务
        QuartzJobDTO job1 = new QuartzJobDTO();
        job1.setBusiId(acti.getId());
        job1.setBusiType(BusiTypeEnum.ACTI_BEGIN.getValue());
        job1.setBusiTime(acti.getActiBeginTime());
        job1.setUserId(acti.getCreatedBy());
        quartzJobDTOList.add(job1);
        // 活动结束任务
        QuartzJobDTO job2 = new QuartzJobDTO();
        job2.setBusiId(acti.getId());
        job2.setBusiType(BusiTypeEnum.ACTI_END.getValue());
        job2.setBusiTime(acti.getActiEndTime());
        job2.setUserId(acti.getCreatedBy());
        quartzJobDTOList.add(job2);
        return quartzJobDTOList;
    }

    /**
     * @Author: ZhaoZiYin
     * @Date: 2025/4/28
     * @Params: [acti]
     * @Return: List<QuartzJobDTO>
     * @Description: 获取入围活动调度任务
     */
    public List<QuartzJobDTO> getJobList4ActiSelect(TActi acti) {
        List<QuartzJobDTO> quartzJobDTOList = new ArrayList<>(2);
        // 活动入围开始任务
        QuartzJobDTO job1 = new QuartzJobDTO();
        job1.setBusiId(acti.getId());
        job1.setBusiType(BusiTypeEnum.ACTI_SELECTED_BEGIN.getValue());
        job1.setBusiTime(acti.getSelectedBeginTime());
        job1.setUserId(acti.getCreatedBy());
        quartzJobDTOList.add(job1);
        // 活动入围结束任务
        QuartzJobDTO job2 = new QuartzJobDTO();
        job2.setBusiId(acti.getId());
        job2.setBusiType(BusiTypeEnum.ACTI_SELECTED_END.getValue());
        job2.setBusiTime(acti.getSelectedEndTime());
        job2.setUserId(acti.getCreatedBy());
        quartzJobDTOList.add(job2);
        return quartzJobDTOList;
    }

    /**
     * @Author: ZhaoZiYin
     * @Date: 2025/4/28
     * @Params: [acti]
     * @Return: List<QuartzJobDTO>
     * @Description: 获取黑箱活动调度任务
     */
    public List<QuartzJobDTO> getJobList4ActiBlack(TActi acti) {
        List<QuartzJobDTO> quartzJobDTOList = new ArrayList<>(2);
        // 活动黑箱开始任务
        QuartzJobDTO job1 = new QuartzJobDTO();
        job1.setBusiId(acti.getId());
        job1.setBusiType(BusiTypeEnum.ACTI_BLACK_BEGIN.getValue());
        job1.setBusiTime(acti.getBlackBeginTime());
        job1.setUserId(acti.getCreatedBy());
        quartzJobDTOList.add(job1);
        // 活动黑箱结束任务
        QuartzJobDTO job2 = new QuartzJobDTO();
        job2.setBusiId(acti.getId());
        job2.setBusiType(BusiTypeEnum.ACTI_BLACK_END.getValue());
        job2.setBusiTime(acti.getBlackEndTime());
        job2.setUserId(acti.getCreatedBy());
        quartzJobDTOList.add(job2);
        return quartzJobDTOList;
    }

    /**
     * @Author: ZhaoZiYin
     * @Date: 2025/4/27
     * @Params: [actiId]
     * @Return: void
     * @Description: 保存活动缓存
     */
    public void saveRedis4Acti(Long actiId) {
        this.saveRedis4Acti(actiId, true);
    }

    /**
     * @Author: ZhaoZiYin
     * @Date: 2025/4/27
     * @Params: [actiId, isSaveStock]
     * @Return: void
     * @Description: 保存活动缓存
     */
    public void saveRedis4Acti(Long actiId, boolean isSaveStock) {
        TActi acti = actiService.getById(actiId);
        List<TActiReward> actiRewardList = actiRewardService.listByActiId(actiId);
        List<TActiFill> actiFillList = actiFillService.listByActiId(actiId);
        this.saveRedis4ActiInfo(acti, actiRewardList, actiFillList);
        this.saveRedis4ActiList(acti);
        if (isSaveStock) {
            this.saveRedis4ActiJoinStock(actiRewardList);
            this.saveRedis4ActiSelectedStock(actiId, acti.getSelectedCount());
            this.saveRedis4ActiBlackStock(actiId, acti.getBlackCount());
        }
        this.saveRedis4ActiStatus(actiId, acti.getActiStatus());
        this.saveRedis4ActiSelectedStatus(actiId, acti.getActiSelectedStatus());
        this.saveRedis4ActiBlackStatus(actiId, acti.getActiBlackStatus());
    }

    /**
     * @Author: ZhaoZiYin
     * @Date: 2025/4/28
     * @Params: [actiId]
     * @Return: void
     * @Description: 删除活动缓存
     */
    public void deleteRedis4Acti(Long actiId) {
        this.deleteRedis4ActiList(actiId);
        redisUtil.delete(RedisKeyConstant.getActiInfoRedisKey(actiId));
        redisUtil.delete(RedisKeyConstant.getActiStatusRedisKey(actiId));
        redisUtil.delete(RedisKeyConstant.getActiSelectedStatusRedisKey(actiId));
        redisUtil.delete(RedisKeyConstant.getActiBlackStatusRedisKey(actiId));
    }

    /**
     * @Author: ZhaoZiYin
     * @Date: 2025/4/29
     * @Params: [acti, actiRewardList, actiFillList]
     * @Return: void
     * @Description: 保存活动信息缓存
     */
    public void saveRedis4ActiInfo(TActi acti, List<TActiReward> actiRewardList, List<TActiFill> actiFillList) {
        ActiQueryResVo resVo = new ActiQueryResVo();
        resVo.build(acti, actiRewardList, actiFillList);
        String key = RedisKeyConstant.getActiInfoRedisKey(acti.getId());
        redisUtil.set(key, JSONObject.toJSONString(resVo));
    }

    /**
     * @Author: ZhaoZiYin
     * @Date: 2025/4/28
     * @Params: [acti]
     * @Return: void
     * @Description: 保存活动列表缓存
     */
    public void saveRedis4ActiList(TActi acti) {
        String key = RedisKeyConstant.ACTI_LIST;
        String actiListStr = redisUtil.get(key);
        if (StringUtils.hasLength(actiListStr)) {
            ActiListResVo resVo = JSONObject.parseObject(actiListStr, ActiListResVo.class);
            if (!CollectionUtils.isEmpty(resVo.getActiList())) {
                // 存在则更新，不存在则新增
                boolean isExit = false;
                for (ActiListResDTO resDTO : resVo.getActiList()) {
                    if (acti.getId().equals(resDTO.getActiId())) {
                        resDTO.build(acti);
                        isExit = true;
                    }
                }
                if (!isExit) {
                    ActiListResDTO resDTO = new ActiListResDTO();
                    resDTO.build(acti);
                    resVo.getActiList().add(resDTO);
                }
                redisUtil.set(key, JSONObject.toJSONString(resVo));
            }
        } else {
            ActiListResVo resVo = new ActiListResVo();
            List<TActi> dbList = new ArrayList<>();
            dbList.add(acti);
            resVo.build(dbList);
            redisUtil.set(key, JSONObject.toJSONString(resVo));
        }
    }

    /**
     * @Author: ZhaoZiYin
     * @Date: 2025/4/30
     * @Params: [actiRewardList]
     * @Return: void
     * @Description: 保存活动商品属性库存缓存
     */
    public void saveRedis4ActiJoinStock(List<TActiReward> actiRewardList) {
        if (CollectionUtils.isEmpty(actiRewardList)) {
            return;
        }
        Map<String, String> redisMap = new HashMap<>();
        for (TActiReward actiReward : actiRewardList) {
            if (actiReward.getActiRewardType() == 1) {
                String prodStr = redisUtil.get(RedisKeyConstant.getStoreProdRedisKey(actiReward.getActiRewardKey()));
                if (StringUtils.hasLength(prodStr)) {
                    StoreProdQueryResVo resVo = JSONObject.parseObject(prodStr, StoreProdQueryResVo.class);
                    if (CollectionUtils.isEmpty(resVo.getProdAttrList())) {
                        continue;
                    }
                    for (StoreProdAttrReqDTO reqDTO : resVo.getProdAttrList()) {
                        String key = RedisKeyConstant.getActiJoinStockRedisKey(actiReward.getActiId(),
                            actiReward.getActiRewardKey(), reqDTO.getProdAttrId());
                        String value = String.valueOf(reqDTO.getStock());
                        redisMap.put(key, value);
                    }
                }
            }
        }
        if (!CollectionUtils.isEmpty(redisMap)) {
            redisUtil.multiSet(redisMap);
        }
    }

    /**
     * @Author: ZhaoZiYin
     * @Date: 2025/5/12
     * @Params: [actiId, selectedCount]
     * @Return: void
     * @Description: 保存入围库存缓存
     */
    public void saveRedis4ActiSelectedStock(Long actiId, Integer selectedCount) {
        String key = RedisKeyConstant.getActiSelectedStockRedisKey(actiId);
        redisUtil.set(key, String.valueOf(selectedCount));
    }

    /**
     * @Author: ZhaoZiYin
     * @Date: 2025/5/12
     * @Params: [actiId, blackCount]
     * @Return: void
     * @Description: 保存黑箱库存缓存
     */
    public void saveRedis4ActiBlackStock(Long actiId, Integer blackCount) {
        String key = RedisKeyConstant.getActiBlackStockRedisKey(actiId);
        redisUtil.set(key, String.valueOf(blackCount));
    }

    /**
     * @Author: ZhaoZiYin
     * @Date: 2025/4/28
     * @Params: [actiId]
     * @Return: void
     * @Description: 删除活动列表缓存
     */
    public void deleteRedis4ActiList(Long actiId) {
        String key = RedisKeyConstant.ACTI_LIST;
        String actiListStr = redisUtil.get(key);
        if (StringUtils.hasLength(actiListStr)) {
            ActiListResVo resVo = JSONObject.parseObject(actiListStr, ActiListResVo.class);
            if (!CollectionUtils.isEmpty(resVo.getActiList())) {
                List<ActiListResDTO> filterActiList = resVo.getActiList().stream()
                    .filter(item -> !actiId.equals(item.getActiId())).collect(Collectors.toList());
                resVo.setActiList(filterActiList);
                redisUtil.set(key, JSONObject.toJSONString(resVo));
            }
        }
    }

    /**
     * @Author: ZhaoZiYin
     * @Date: 2025/4/27
     * @Params: [actiId, actiStatus]
     * @Return: void
     * @Description: 保存活动状态缓存
     */
    public void saveRedis4ActiStatus(Long actiId, Integer actiStatus) {
        String key = RedisKeyConstant.getActiStatusRedisKey(actiId);
        redisUtil.set(key, String.valueOf(actiStatus));
    }

    /**
     * @Author: ZhaoZiYin
     * @Date: 2025/4/27
     * @Params: [actiId, actiSelectedStatus]
     * @Return: void
     * @Description: 保存活动入围状态缓存
     */
    public void saveRedis4ActiSelectedStatus(Long actiId, Integer actiSelectedStatus) {
        String key = RedisKeyConstant.getActiSelectedStatusRedisKey(actiId);
        redisUtil.set(key, String.valueOf(actiSelectedStatus));
    }

    /**
     * @Author: ZhaoZiYin
     * @Date: 2025/4/27
     * @Params: [actiId, actiBlackStatus]
     * @Return: void
     * @Description: 保存活动黑箱状态缓存
     */
    public void saveRedis4ActiBlackStatus(Long actiId, Integer actiBlackStatus) {
        String key = RedisKeyConstant.getActiBlackStatusRedisKey(actiId);
        redisUtil.set(key, String.valueOf(actiBlackStatus));
    }

    /**
     * @Author: ZhaoZiYin
     * @Date: 2025/4/22
     * @Params: [reqVo]
     * @Return: ActiJoinSelectedResVo
     * @Description: 参与入围活动
     */
    public ActiJoinSelectedResVo joinSelectedToRedis(ActiJoinSelectedReqVo reqVo) {
        // 校验入围活动状态是否为进行中
        actiService.joinSelectedCheck(reqVo.getActiId());
        // 校验用户是否已入围
        actiJoinService.joinSelectedCheck(reqVo.getUserId(), reqVo.getActiId(), reqVo.getSelectedJoinType());
        // 参与活动业务处理
        return actiJoinService.joinSelectedToRedis(reqVo);
    }

    /**
     * @Author: ZhaoZiYin
     * @Date: 2025/4/22
     * @Params: [reqVo]
     * @Return: ActiJoinSelectedResVo
     * @Description: 参与入围活动
     */
    @Transactional(rollbackFor = Exception.class)
    public void joinSelectedToDb(ActiJoinSelectedReqVo reqVo) {
        actiJoinService.deleteJoin(reqVo.getActiId(), reqVo.getUserId(), ActiJoinKindEnum.SELECTED.getValue());
        actiJoinService.joinSelected(reqVo);
        actiJoinFillService.deleteJoin(reqVo.getActiId(), reqVo.getUserId());
        actiJoinFillService.joinToDb(reqVo.getUserId(), reqVo.getActiId(), reqVo.getFillList());
        actiJoinProdService.deleteJoin(reqVo.getActiId(), reqVo.getUserId());
        actiJoinProdService.joinToDb(reqVo.getUserId(), reqVo.getActiId(), reqVo.getProdList());
        actiJoinProdAttrService.deleteJoin(reqVo.getActiId(), reqVo.getUserId());
        actiJoinProdAttrService.joinToDb(reqVo.getUserId(), reqVo.getActiId(), reqVo.getProdList());
    }

    /**
     * @Author: ZhaoZiYin
     * @Date: 2025/4/22
     * @Params: [reqVo]
     * @Return: ActiJoinResVo
     * @Description: 参与活动
     */
    public ActiJoinResVo joinToRedis(ActiJoinReqVo reqVo) {
        // 校验活动状态是否为进行中
        actiService.joinCheck(reqVo.getActiId());
        // 校验用户状态是否已中选
        actiJoinService.joinCheck(reqVo.getUserId(), reqVo.getActiId(), reqVo.getActiJoinType(),
            reqVo.getSelectedFlag());
        // 手速活动校验商品库存
        if (reqVo.getActiJoinType() == ActiJoinTypeEnum.QUICK.getValue()) {
            actiJoinService.joinProdCheck(reqVo.getActiId(), reqVo.getProdList());
        }
        // 参与活动业务处理
        return actiJoinService.joinToRedis(reqVo);
    }

    /**
     * @Author: ZhaoZiYin
     * @Date: 2025/4/22
     * @Params: [reqVo]
     * @Return: ActiJoinResVo
     * @Description: 参与活动
     */
    @Transactional(rollbackFor = Exception.class)
    public void joinToDb(ActiJoinReqVo reqVo) {
        actiJoinService.deleteJoin(reqVo.getActiId(), reqVo.getUserId(), ActiJoinKindEnum.JOIN.getValue());
        actiJoinService.joinToDb(reqVo);
        actiJoinFillService.deleteJoin(reqVo.getActiId(), reqVo.getUserId());
        actiJoinFillService.joinToDb(reqVo.getUserId(), reqVo.getActiId(), reqVo.getFillList());
        actiJoinProdService.deleteJoin(reqVo.getActiId(), reqVo.getUserId());
        actiJoinProdService.joinToDb(reqVo.getUserId(), reqVo.getActiId(), reqVo.getProdList());
        actiJoinProdAttrService.deleteJoin(reqVo.getActiId(), reqVo.getUserId());
        actiJoinProdAttrService.joinToDb(reqVo.getUserId(), reqVo.getActiId(), reqVo.getProdList());
    }

    /**
     * @Author: ZhaoZiYin
     * @Date: 2025/4/22
     * @Params: [reqVo]
     * @Return: ActiJoinSelectedResVo
     * @Description: 参与入围活动
     */
    public ActiJoinBlackResVo joinBlackToRedis(ActiJoinBlackReqVo reqVo) {
        // 校验活动状态是否为进行中
        actiService.joinBlackCheck(reqVo.getActiId());
        // todo 校验用户是否拥有黑箱卡
        // 校验用户状态是否已中选
        actiJoinService.joinCheck(reqVo.getUserId(), reqVo.getActiId(), ActiJoinTypeEnum.QUICK.getValue(), 0);
        // 参与活动业务处理
        return actiJoinService.joinBlackToRedis(reqVo);
    }

    /**
     * @Author: ZhaoZiYin
     * @Date: 2025/4/22
     * @Params: [reqVo]
     * @Return: ActiJoinBlackResVo
     * @Description: 参与黑箱活动
     */
    @Transactional(rollbackFor = Exception.class)
    public void joinBlackToDb(ActiJoinBlackReqVo reqVo) {
        actiJoinService.deleteJoin(reqVo.getActiId(), reqVo.getUserId(), ActiJoinKindEnum.BLACK.getValue());
        actiJoinService.joinBlack(reqVo);
        actiJoinFillService.deleteJoin(reqVo.getActiId(), reqVo.getUserId());
        actiJoinFillService.joinToDb(reqVo.getUserId(), reqVo.getActiId(), reqVo.getFillList());
        actiJoinProdService.deleteJoin(reqVo.getActiId(), reqVo.getUserId());
        actiJoinProdService.joinToDb(reqVo.getUserId(), reqVo.getActiId(), reqVo.getProdList());
        actiJoinProdAttrService.deleteJoin(reqVo.getActiId(), reqVo.getUserId());
        actiJoinProdAttrService.joinToDb(reqVo.getUserId(), reqVo.getActiId(), reqVo.getProdList());
    }

    /**
     * @Author: ZhaoZiYin
     * @Date: 2025/6/5
     * @Params: [reqVo]
     * @Return: ActiSaveUserImgResVo
     * @Description: 保存活动用户返图
     */
    public ActiSaveUserImgResVo saveUserImg(ActiSaveUserImgReqVo reqVo) {
        ActiSaveUserImgResVo resVo = new ActiSaveUserImgResVo();
        TActiUserImg userImg = reqVo.build();
        actiUserImgService.save(userImg);
        return resVo;
    }

}
